package com.framework.mybatis.core.mapper;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.framework.mybatis.core.pojo.PageParam;
import com.framework.mybatis.core.pojo.PageResult;
import com.framework.mybatis.core.util.MyBatisUtils;
import com.github.yulichang.base.MPJBaseMapper;
import org.apache.ibatis.annotations.Param;

import java.util.Collection;
import java.util.List;

/**
 * @author shen_dy@halcyonz.com
 * @date 2024/3/30
 */
public interface BaseMapperX<T> extends MPJBaseMapper<T> {

	default PageResult<T> selectPage(PageParam pageParam, @Param("ew") Wrapper<T> queryWrapper) {
		// MyBatis Plus 查询
		IPage<T> mpPage = MyBatisUtils.buildPage(pageParam);
		selectPage(mpPage, queryWrapper);
		// 转换返回
		//        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
		// 修改分页，增加当前页号和总页数 at 2023-11-14
		return new PageResult<>(mpPage.getRecords(), mpPage.getTotal(), mpPage.getCurrent(), mpPage.getPages());
	}

	default T selectOne(String field, Object value) {
		return selectOne(new QueryWrapper<T>().eq(field, value));
	}

	default T selectOne(SFunction<T, ?> field, Object value) {
		return selectOne(new LambdaQueryWrapper<T>().eq(field, value));
	}

	default T selectOne(String field1, Object value1, String field2, Object value2) {
		return selectOne(new QueryWrapper<T>().eq(field1, value1).eq(field2, value2));
	}

	default T selectOne(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2) {
		return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
	}

	default T selectOne(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2,
		SFunction<T, ?> field3, Object value3) {
		return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2)
			.eq(field3, value3));
	}

	default Long selectCount() {
		return selectCount(new QueryWrapper<T>());
	}

	default Long selectCount(String field, Object value) {
		return selectCount(new QueryWrapper<T>().eq(field, value));
	}

	default Long selectCount(SFunction<T, ?> field, Object value) {
		return selectCount(new LambdaQueryWrapper<T>().eq(field, value));
	}

	default List<T> selectList() {
		return selectList(new QueryWrapper<>());
	}

	default List<T> selectList(String field, Object value) {
		return selectList(new QueryWrapper<T>().eq(field, value));
	}

	default List<T> selectList(SFunction<T, ?> field, Object value) {
		return selectList(new LambdaQueryWrapper<T>().eq(field, value));
	}

	default List<T> selectList(String field, Collection<?> values) {
		if (CollUtil.isEmpty(values)) {
			return CollUtil.newArrayList();
		}
		return selectList(new QueryWrapper<T>().in(field, values));
	}

	default List<T> selectList(SFunction<T, ?> field, Collection<?> values) {
		if (CollUtil.isEmpty(values)) {
			return CollUtil.newArrayList();
		}
		return selectList(new LambdaQueryWrapper<T>().in(field, values));
	}

	default List<T> selectList(SFunction<T, ?> leField, SFunction<T, ?> geField, Object value) {
		return selectList(new LambdaQueryWrapper<T>().le(leField, value).ge(geField, value));
	}

	/**
	 * 批量插入，适合大量数据插入
	 *
	 * @param entities 实体们
	 */
	default void insertBatch(Collection<T> entities) {
		Db.saveBatch(entities);
	}

	/**
	 * 批量插入，适合大量数据插入
	 *
	 * @param entities 实体们
	 * @param size     插入数量 Db.saveBatch 默认为 1000
	 */
	default void insertBatch(Collection<T> entities, int size) {
		Db.saveBatch(entities, size);
	}

	default void updateBatch(T update) {
		update(update, new QueryWrapper<>());
	}

	default void updateBatch(Collection<T> entities) {
		Db.updateBatchById(entities);
	}

	default void updateBatch(Collection<T> entities, int size) {
		Db.updateBatchById(entities, size);
	}

	default void saveOrUpdateBatch(Collection<T> collection) {
		Db.saveOrUpdateBatch(collection);
	}

}
